/***************************************************************************
 *   Copyright (C) 2009 by pawel   *
 *   pawel@byszewski.pl   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#ifndef DESMENAGER_H
#define DESMENAGER_H

#include <fcntl.h>
#include "settings.h"
#include "recdes.h"
#include "helpers.h"

using namespace std;

/**
	@author pawel <pawel@byszewski.pl>
*/
class DesMenager{
	private:
		int fd;
		
		unsigned int desCount;
		struct flock fl;
public:
    DesMenager(int _fd){
	    fd=_fd;
	    desCount=10;
    }
    
    void resize(int i){
	    int dl,pos;
	    int ofestDoZapisu;
	    cout<<" i: "<<i<<endl;
	    dl=lseek(fd, 0, SEEK_END);
	    ofestDoZapisu=dl;
	    cout << "przed powiekszeniem koniec jest w: "<<dl<<endl;
	    dl=lseek(fd, (i*DESLENGTH)-1, SEEK_END);
	    cout <<"DESLENGTH: "<<DESLENGTH<<" i: "<<i<<endl;
	    cout <<"przesunieto o: "<<(i*DESLENGTH)<<"  na pozycje: "<<dl<<endl;
	    pos=write(fd, "q", 1);
	    desCount+=i;
	    createEmptyDes(int(i/DESLENGTH), ofestDoZapisu);
	//cout <<"       po write: "<<pos <<endl;
	//dl=lseek(fd, 0,SEEK_END);
	//cout <<" w funkcji 2: "<<dl<<endl;
    }
    /*i-ilosc deskryptorow, of-ofset od krórego zaczać tworzyć puste
    *zakladam ze jak to wywolujemy to jest plik jest juz wystarczająco duży
    */
    void createEmptyDes(int n, int of){
    	lseek(fd, of, SEEK_SET);
	char *temp =new char[5];
	temp[0]=temp[1]=temp[2]=temp[3]=temp[4]=0;
	for(int i=0;i<n;++i){
	//	lseek(fd, (i*of); SEEK_SET);
		write(fd, temp, 5);
		lseek(fd, (DESLENGTH-5), SEEK_CUR);
	}
    }
    /*przez ofset jest zwracana wartość ofestu pod którym lezy deskryptor
    * nalezy pamietac ze po wyjsciu z tej funkcji zalozona jest blokada 
     na rekordzie pliku w ktorym lezy dekryptor wiec tzeba pmietac że później należy jąd zdjąć
    */
     void findEmptyDes(int size, int *ofset, unsigned int *s){
	    unsigned int fileSize=lseek(fd,0,SEEK_END);
	     
	     	fl.l_whence=SEEK_SET;
	    while(1){
	     for(int i=0; (i*DESLENGTH)<fileSize;++i){

		cout <<"\t"<<i<<" obrot petli"<<fileSize <<endl;
		fl.l_start=i*DESLENGTH;
		fl.l_len=DESLENGTH;
		fl.l_type=F_WRLCK;//@TODO zmienic zeby najpier byla zapisu a dopiero potem odczytu
		fcntl(fd, F_SETLK, &fl);
			if(0==isBooked(i*DESLENGTH)){//bycmoze znaleziony
				unsigned int _size= checkSize(i*DESLENGTH);
				cout <<"docelowy rozmiar: "<<size<<endl;
				if(size<=_size || _size==0){//napewno znaleziony
					*ofset=i*DESLENGTH;
					*s=_size;
					cout<<"SUKCES znaleziono na ofsecie: "<<i*DESLENGTH<<endl;
					return;//spadamy stąd bo znaleźliśmy
				}
			}
		//ten sie nie nadaje wiec zwalzniam blokade i lece dalej
		fl.l_type=F_UNLCK;
		fcntl(fd, F_SETLK, &fl);
		//jescze raz patrze rozmiar bo moglo sie coś pozmieniać
		fileSize=lseek(fd,0,SEEK_END);
		
			
	     }
	     cout << "zwiekszanie pliku z deskryptorami"<<endl;
	     *ofset=-1;
			fl.l_start=0;
			fl.l_len=0;
			fl.l_type=F_WRLCK;
			fcntl(fd, F_SETLK, &fl);
			resize(10);
			close(fd);
			fd=open("DESC",	 O_CREAT | O_RDWR, 07777);
	    };
	}
	void unlock(){
		fl.l_type=F_UNLCK;
		fcntl(fd, F_SETLK, &fl);
	}
	
	int isBooked(int of){
		lseek(fd, of, SEEK_SET);
		//cout<<"czytam czy jest zajety dla ofsetu: "<<of<<endl;
		char *b=new char[4];
		b[0]=b[1]=b[2]=b[3]=0;
		read(fd, b, 1);
		int *k=(int*)b;
		//cout<<"isBooked: "<<*k<<"*"<<*b<<endl;
		return *k;
	}
	unsigned int checkSize(int of){
		char *load = new char[4];
		lseek(fd,of+1,SEEK_SET);//dadaje 1 do ofsetu bo size zaczyna sie na pierwszym(a nie zerowym) bajcie
		read(fd, load, 4);
		unsigned int *k=(unsigned int *)load;
		cout <<"size : "<<*k<<endl;
		return *k;
	}
	unsigned int createDataOfset(unsigned int desOf){
		struct flock flo;
		RecordDescriptor des;
		flo.l_whence=SEEK_SET;
		flo.l_start=desOf-DESLENGTH;
		flo.l_len=DESLENGTH;
		flo.l_type=F_RDLCK;
		fcntl(fd, F_SETLK, &flo);
			char *buf=new char[DESLENGTH];
			lseek(fd,desOf-DESLENGTH, SEEK_SET);
			read(fd, buf, DESLENGTH);
			des.createFromBuf(buf);
			flo.l_type=F_UNLCK;
		fcntl(fd, F_SETLK, &flo);
		return (des.getSize()+des.getOfset()+1);
	}
	void deactive(int nr){
		int d=nr;
		if(nr>0) --d;
		struct flock flo;
		flo.l_whence=SEEK_SET;
		flo.l_start=d*DESLENGTH;
		flo.l_len=DESLENGTH;
		flo.l_type=F_WRLCK;
		fcntl(fd, F_SETLK, &flo);
			lseek(fd,d*DESLENGTH, SEEK_SET);
			char temp=0;
			write(fd, &temp,1);
			flo.l_type=F_UNLCK;
		fcntl(fd, F_SETLK, &flo);
	}
	
	int findSimilary(int *n,  RecordDescriptor **des){
		unsigned int fileSize=lseek(fd,0,SEEK_END);
	     
		fl.l_whence=SEEK_SET;
		char *buf=new char[DESLENGTH];
		for(int i=*n; (i*DESLENGTH)<=fileSize;++i){
			
			//cout <<"\t\t\t"<<i<<" obrot petli   czytamy od: "<<(i*DESLENGTH)<<endl;
			fl.l_start=i*DESLENGTH;
			fl.l_len=DESLENGTH;
			fl.l_type=F_WRLCK;
			fcntl(fd, F_SETLK, &fl);
			//DEBUGINFO("find similary", "przed sprawdaniem zajetosci");
			if(1==isBooked(i*DESLENGTH)){//bycmoze znaleziony
				//DEBUGINFO("find similary", "po sprawdaniem zajetosci");
				int dl=lseek(fd,i*DESLENGTH, SEEK_SET);
				//cout <<" czytany z przesuniecia: "<<dl<<endl;
				read(fd, buf, DESLENGTH);
				 RecordDescriptor *des1=new RecordDescriptor();
				 des1->createFromBuf(buf);
				 //cout <<"---"<<i<<"----";
				 //des1->wypisz();
				 if(des1->isSimilar(*des)){
					 *des=des1;
					 *n=i+1;
					 return 1;
				 };
			}
		//ten sie nie nadaje wiec zwalzniam blokade i lece dalej
			fl.l_type=F_UNLCK;
			fcntl(fd, F_SETLK, &fl);
		//jescze raz patrze rozmiar bo moglo sie coś pozmieniać
			fileSize=lseek(fd,0,SEEK_END);
			
			
		}
		return 0;
	}
    ~DesMenager()
    {

    };

};

#endif
